home *** CD-ROM | disk | FTP | other *** search
- /*
- This is a small kb to experiment with object-oriented
- programming in M1.
- */
-
- /*
- 9/90 -- This is a small kb to illustrate the use of object-
- oriented programming. The domain is planes and flying. This
- was chosen to reflect a number of the examples in the M.1 v3
- documentation. The main procedure is 'simulate', which allows
- you to select a plane and then execute various actions
- (load, unload, take-off, fly, etc.).
-
- 11/90 -- Modified kb to make it clearer from a user's
- perspective. One speed is asked, instead of x- and y-
- velocities. Expressions that might need to be asked a number of
- times (for repeated actions) are nocache.
- - To be robust, all expressions should have some default.
- There should be some 'common sense' rules, such as checking
- for reasonable speeds, altitudes, etc. For example, it doesn't
- make sense to fly or descent if you're on the ground; you
- shouldn't be able to go to a negative altitude...
- - There are places that I've put NOTES for a future developer--
- they should be read and removed before this is made a sample kb.
-
- */
-
- initialdata = [welcome, simulate].
-
- /*------------------ Class and Instance Definitions ---------*/
-
- classdef(moving_object) = [
- supers = [],
- x_position = 0,
- y_position = 0,
- x_velocity = 0,
- y_velocity = 0
- ].
-
- classdef(means_of_transportation) = [
- supers = [],
- arrival_time,
- departure_time,
- carrying_capacity,
- fuel_capacity
- ].
-
- classdef(airplane) = [
- supers = [moving_object, means_of_transportation],
- airplane_id_number,
- name,
- altitude = 0
- ].
-
- classdef(passenger_plane) = [
- supers = [airplane],
- number_of_passengers = 0,
- passenger_capacity
- ].
-
- classdef(cargo_plane) = [
- supers = [airplane],
- tonnage_capacity,
- cargo = []
- ].
-
- /* A few instances */
- instdef(anemone) = [
- class = passenger_plane,
- passenger_capacity = 120,
- name = "anemone"
- ].
-
- instdef(urchin) = [
- class = passenger_plane,
- passenger_capacity = 80,
- name = "urchin"
- ].
-
- instdef(sea_spray) = [
- class = cargo_plane,
- name = sea_spray
- ].
-
- instdef(sea_breeze) = [
- class = cargo_plane,
- name = sea_breeze
- ].
-
- /*-------------------- add_list -------------------------*/
- add_list(CAR, []) = [CAR].
-
- add_list(CAR, [FIRST]) = [CAR, FIRST].
-
- add_list(CAR, [FIRST | REST]) = [CAR, FIRST | REST].
-
- nocache(add_list(X,Y)).
-
-
- /*------------------- ascent_angle ---------------------*/
- nocache(ascent_angle).
-
- question(ascent_angle) = 'What is the ascent angle (in
- increments of 5 degrees)?'.
-
- legalvals(ascent_angle) = [5, 10, 15, 20, 25, 30, 35, 40, 45].
-
- /*------------------- ascent_altitude ------------------*/
- nocache(ascent_altitude).
-
- question(ascent_altitude) = 'To what altitude do you wish to
- ascend, in feet? (answer unknown if you prefer to specify angle)'.
-
-
- /*------------------- ask_elapsed_time -----------------*/
-
- question(ask_elapsed_time) = "How long has the object been
- moving?".
-
- /*----- <- adjust_altitude(XVEL, YVEL, ASCENT_TIME) ---*/
-
- procedure(airplane <- adjust_altitude(XVEL, YVEL, ASCENT_TIME)) = {
- eval SELF <- setslot(x_velocity, XVEL);
- eval SELF <- setslot(y_velocity, YVEL);
- eval SELF <- move(ASCENT_TIME);
- display("New position is: ");
- eval SELF <- print_position;
- }.
-
- /*----------------- cargo_to_load -------------------------*/
-
- question(cargo_to_load) = 'What cargo do you wish loaded?'.
-
- /*---------- <- cargo_unloaded --------------------*/
-
- if SELF <- getslot(cargo) = CARGO and
- SELF <- unload(CARGO)
- then cargo_plane <- cargo_unloaded.
-
- /*----- calculate_ascent_velocity(PLANE, ALTITUDE, TIME) --*/
-
- nocache(calculate_ascent_velocity(X, Y, Z)).
-
- if PLANE <- getslot(y_position) = Y_POS and
- ALTITUDE - Y_POS = POSITION_CHANGE and
- POSITION_CHANGE/TIME = Y_VEL and
- display(['The required ascent velocity is ', Y_VEL, ' mph.',
- nl])
- then calculate_ascent_velocity(PLANE, ALTITUDE, TIME) = Y_VEL.
-
- /*----- calculate_descent_velocity(PLANE, ALTITUDE, TIME) --*/
-
- nocache(calculate_descent_velocity(X, Y, Z)).
-
- if PLANE <- getslot(y_position) = Y_POS and
- ALTITUDE - Y_POS = POSITION_CHANGE and
- POSITION_CHANGE/TIME = Y_VEL and
- display(['The required descent velocity is ', Y_VEL, ' mph.',
- nl])
- then calculate_descent_velocity(PLANE, ALTITUDE, TIME) = Y_VEL.
-
- /*------------ <- calculate_elapsed_time ------------*/
-
- if ask_elapsed_time = TIME
- then moving_object <- calculate_elapsed_time = TIME.
-
- /*------------------ cos(ANGLE) ---------------------*/
- /*
- This is a fact table to look up cos of an angle.
- This is used to compute x and y velocities from
- speed. This table could be replaced by external
- functions.
- */
-
- cos(5) = 1.
- cos(10) = 0.98.
- cos(15) = 0.97.
- cos(20) = 0.94.
- cos(25) = 0.91.
- cos(30) = 0.89.
- cos(35) = 0.82.
- cos(40) = 0.77.
- cos(45) = 0.71.
-
- /*------------ <- create_initialize ------------------*/
- /* NOTE: The idea here was to be able to use the airplane rule
- as a super for teh cargo_plane and passenger_plane subclasses.
- But you can only create one of these (either the class or the
- subclass) for each instance, so it doesn't work to do that.
- The subclasses should probably ask crew and position, if it
- matters. The positions are initialized to 0.
- */
-
- if airplane <- new = NEW and
- NEW <- setslot(name, PLANE_NAME) and
- NEW <- setslot(crew, CREW_SIZE) and
- NEW <- setslot(x_position, XPOS) and
- NEW <- setslot(y_position, YPOS)
- then airplane <- create_initialize(PLANE_NAME, CREW_SIZE, XPOS, YPOS).
-
- if cargo_plane <- new = NEW and
- plane_name = NAME and
- NEW <- setslot(name, NAME)
- then cargo_plane <- create_initialize = NEW.
-
- if passenger_plane <- new = NEW and
- plane_name = NAME and
- passenger_capacity = CAPACITY and
- NEW <- setslot(name, NAME) and
- NEW <- setslot(passenger_capacity, CAPACITY)
- then passenger_plane <- create_initialize = NEW.
-
-
- /*------------ descent_altitude -----------------------*/
-
- nocache(descent_altitude).
-
- question(descent_altitude) = 'To what altitude do you wish to
- descend, in feet? (answer unknown if you prefer to specify angle)'.
-
- /*------------------- descent_angle ---------------------*/
- nocache(descent_angle).
-
- question(descent_angle) = 'What is the descent angle (in
- increments of 5 degrees)?'.
-
- legalvals(descent_angle) = [5, 10, 15, 20, 25, 30, 35, 40, 45].
-
-
- /*--------------- find_desired_plane ------------------*/
-
- procedure(find_desired_plane) = {
- TYPE := plane_type;
- find known_plane;
- if known_plane = known {
- find set_legalvals(plane_name(TYPE));
- find plane_name(TYPE);
- forall classinst(TYPE, POSSIBLE_PLANE) {
- NAME := POSSIBLE_PLANE <- getslot(name);
- if plane_name(TYPE) = NAME {
- PLANE :== POSSIBLE_PLANE;
- break;
- };
- };
- }
- else {
- PLANE := TYPE <- create_initialize;
- };
- display(['Plane characteristics are: ', nl]);
- eval PLANE <- printself;
- return PLANE;
- }.
-
- /*----------------- <- fly(XVEL, YVEL, TIME) ----------*/
-
- procedure(airplane <- fly(XVEL, YVEL, TIME)) = {
- /* Note: Could alternately use set_and_print_velocity,
- as in the addendum, with the addition of a TIME
- parameter argument. */
-
- eval SELF <- set_velocity(XVEL, YVEL);
- eval SELF <- move(TIME);
- display("New position is: ");
- eval SELF <- print_position;
- }.
-
- /*--------------------- flying_time --------------------*/
- nocache(flying_time).
-
- question(flying_time) = 'What is the flying time at this
- speed, in hours?'.
-
- /*--------------------- get_plane_list ---------------*/
- nocache(get_plane_list(TYPE)).
-
-
- procedure(get_plane_list(TYPE)) = {
- /* NOTE: I'd like to use listof to collect the planes,
- but it doesn't seem to work.
- listof(NAME, classinst(TYPE, PLANE) and
- NAME := PLANE <- getslot(name)) = PLANELIST
- */
- PLANELIST :== [];
- forall classinst(TYPE, PLANE) {
- NAME := PLANE <- getslot(name);
- PLANELIST := add_list(NAME, PLANELIST);
- };
- return PLANELIST;
- }.
-
-
-
- /*----------------- <- get_speed --------------------*/
-
- procedure(moving_object <- get_speed) = {
- X := SELF <- getslot(x_velocity);
- Y := SELF <- getslot(y_velocity);
- SPEED := sqrt((X*X) + (Y*Y));
- return SPEED;
- }.
-
- /*------------------ known_plane ---------------------------*/
-
- question(known_plane) = 'Would you like to fly a known plane or
- specify a new plane?'.
-
- legalvals(known_plane) = [known, new].
-
-
- /*---------------- <- load ---------------------------*/
-
- procedure(cargo_plane <- load) = {
- CARGO := cargo_to_load;
- OLDCARGO := SELF <- getslot(cargo);
- NEWCARGO := add_list(CARGO, OLDCARGO);
- NAME := SELF <- getslot(name);
- display(["Loading ", NAME, " with ", CARGO, ". Cargo now is: ",
- NEWCARGO, nl]);
- eval SELF <- setslot(cargo, NEWCARGO);
- reset cargo_to_load;
- }.
-
- procedure(passenger_plane <- load) = {
- PASS := passenger_number;
- OLDPASS := SELF <- getslot(number_of_passengers);
- NEWPASS := OLDPASS + PASS;
- NAME := SELF <- getslot(name);
- /* should check that NEWPASS does not exceed passenger
- capacity */
- CAPACITY := SELF <- getslot(passenger_capacity);
- if CAPACITY >= NEWPASS {
- display(["Loading ", NAME, " with ", PASS, "
- passengers. Total passengers is now: ", NEWPASS, nl]);
- eval SELF <- setslot(number_of_passengers, NEWPASS);
- }
- else {
- display(["The passenger capacity for ", NAME, " is ",
- CAPACITY, " which is less than the resulting passenger count of ",
- NEWPASS, ". The ", PASS, " new passengers were not loaded.", nl]);
- };
- reset passenger_number;
- }.
-
- /*----------------- <- move(ELAPSED_TIME) -------------*/
-
- procedure(moving_object <- move(ELAPSED_TIME)) = {
- X_POS := SELF <- getslot(x_position);
- Y_POS := SELF <- getslot(y_position);
- X_VEL := SELF <- getslot(x_velocity);
- Y_VEL := SELF <- getslot(y_velocity);
- NEW_X := X_POS + (X_VEL * ELAPSED_TIME);
- NEW_Y := Y_POS + (Y_VEL * ELAPSED_TIME);
- eval SELF <- set_position(NEW_X, NEW_Y);
- ALT := NEW_Y * 5280;
- eval SELF <- setslot(altitude, ALT);
- }.
-
- /*-------------------- newlegalvals(plane_name(TYPE)) -------*/
- nocache(newlegalvals(plane_name(TYPE))).
-
- if get_plane_list(TYPE) = PLANELIST
- then newlegalvals(plane_name(TYPE)) = PLANELIST.
-
-
- /*---------------------- next_action ----------------*/
-
- question(next_action) = 'What is the next action you wish to
- take?'.
-
- legalvals(next_action) = [load, take_off, ascend, fly, descend,
- land, check_position, unload, display_plane, select_plane,
- show_planes, stop].
-
- /*------------------ passenger_capacity ----------------*/
-
- question(passenger_capacity) = 'What is the passenger capacity
- of the plane?'.
-
- legalvals(passenger_capacity) = integer.
-
- /*------------------ passenger_number ------------------*/
-
- question(passenger_number) = 'How many new passengers are
- there?'.
-
- legalvals(passenger_number) = integer.
-
- /*--------------------- plane_name ----------------------*/
-
- question(plane_name) = 'What is the name of the plane?'.
-
- /*------------- plane_name(cargo_plane) ----------------------*/
-
- question(plane_name(cargo_plane)) = 'What is the name of the cargo plane?'.
-
- legalvals(plane_name(cargo_plane)) = [sea_spray].
-
- /*----------- plane_name(passenger_plane) ----------------------*/
-
- question(plane_name(passenger_plane)) = 'What is the name of the
- passenger plane?'.
-
- legalvals(plane_name(passenger_plane)) = [anemone].
-
- /*-------------------- plane_type -----------------------*/
-
- question(plane_type) = 'Would you like to fly a cargo or
- a passenger plane?'.
-
- legalvals(plane_type) = [cargo_plane, passenger_plane].
-
- /*----------------------- <- print_position -----------*/
-
- procedure(moving_object <- print_position) = {
- XPOS := SELF <- getslot(x_position);
- YPOS := SELF <- getslot(y_position);
- display(["X = ", XPOS, " miles, Y = ", YPOS, " miles.", nl]);
- }.
-
- procedure(airplane <- print_position) = {
- eval SUPER <- print_position;
- ALT := SELF <- getslot(altitude);
- display([" Altitude = ", ALT, " feet.", nl]);
- }.
-
- /*--------------- process(ascend, PLANE) ---------------*/
-
- procedure(process(ascend, PLANE)) = {
- SPD := speed;
- TIME := ascent-time;
- if ascent_altitude is known {
- ASCENT_ALT := ascent_altitude;
- ALT := ASCENT_ALT/5280;
- Y_VEL := calculate_ascent_velocity(PLANE, ALT, TIME);
- X_VEL := sqrt((SPD * SPD) - (Y_VEL * Y_VEL));
- }
- else {
- if ascent_angle is known {
- ANGLE := ascent_angle;
- COS := cos(ANGLE);
- SIN := sin(ANGLE);
- X_VEL := COS * SPD;
- Y_VEL := SIN * SPD;
- }
- else {
- /* should set some defaults */
- };
- };
- eval PLANE <- adjust_altitude(X_VEL, Y_VEL, TIME);
- }.
-
- /*---------------- process(check_position, PLANE) ------*/
-
- procedure(process(check_position, PLANE)) = {
- eval PLANE <- print_position;
- }.
-
- /*--------------- process(descend, PLANE) ---------------*/
-
- procedure(process(descend, PLANE)) = {
- SPD := speed;
- TIME := descent-time;
- if descent_altitude is known {
- DESCENT_ALT := descent_altitude;
- ALT := DESCENT_ALT/5280;
- Y_VEL := calculate_descent_velocity(PLANE, ALT, TIME);
- X_VEL := sqrt((SPD * SPD) - (Y_VEL * Y_VEL));
- }
- else {
- if descent_angle is known {
- ANGLE := descent_angle;
- COS := cos(ANGLE);
- SIN := sin(ANGLE);
- X_VEL := COS * SPD;
- Y_VEL := 0 - SIN * SPD;
- }
- else {
- /* should set some defaults */
- };
- };
- eval PLANE <- adjust_altitude(X_VEL, Y_VEL, TIME);
- }.
-
- /*---------------- process(display_plane, PLANE) -------*/
-
- procedure(process(display_plane, PLANE)) = {
- eval PLANE <- printself;
- }.
-
- /*-------------- process(fly, PLANE) --------------------*/
- procedure(process(fly, PLANE)) = {
- SPD := speed;
- F := flying_time;
- eval PLANE <- fly(SPD, 0, F);
- }.
-
- /*--------------- process(land, PLANE) ---------------*/
-
- procedure(process(land, PLANE)) = {
- Y_POS := PLANE <- getslot(y_position);
- if (Y_POS > 0) {
- set descent_altitude = 0;
- eval process(descend, PLANE);
- reset process(descend, PLANE);
- }
- else {
- display(["A plane must be in the air in order to land.", nl]);
- };
- }.
-
-
- /*------------- process(load, PLANE) ---------------------*/
-
- procedure(process(load, PLANE)) = {
- eval PLANE <- load;
- }.
-
- /*------------ process(show_planes, PLANE) ---------------*/
- procedure(process(show_planes, PLANE)) = {
- /* NOTE: What I'd like is a way of finding all the
- subclasses of a class to use with classinst, and
- thus to show the planes in each subclass. */
- TYPE := plane_type;
- NAME := PLANE <- getslot(name);
- PLANES := get_plane_list(TYPE);
- display(['The currently selected plane is ', NAME, '.', nl]);
- display(['The known planes of type ', TYPE, ' are: ', PLANES,
- nl]);
- }.
-
- /*------------ process(take_off, PLANE) ------------------*/
-
- procedure(process(take_off, PLANE)) = {
- Y_POS := PLANE <- getslot(y_position);
- if (Y_POS == 0) {
- eval process(ascend, PLANE);
- reset process(ascend, PLANE);
- }
- else {
- display(["A plane must be on the ground in order to take
- off.", nl]);
- };
- }.
-
- /*-------------- process(unload, PLANE) ------------------*/
-
- procedure(process(unload, PLANE)) = {
- eval PLANE <- unload;
- }.
-
- /*-------------- <- set_and_print_velocity(XVEL, YVEL) ----*/
-
- procedure(airplane <- set_and_print_velocity(XVEL, YVEL)) = {
- NAME := SELF <- getslot(name);
- display(["Setting ", NAME, "'s velocity: ", nl]);
- eval SELF <- set_velocity(XVEL, YVEL);
- display(["Moving ", NAME, nl]);
- TIME := SELF <- calculate_elapsed_time;
- eval SELF <- move(TIME);
- eval SELF <- printself;
- }.
-
- /*------------------- set_legalvals(X) ----------------*/
- nocache(set_legalvals(EXPR)).
-
- if kbentry(L:legalvals(EXPR) = LIST) and
- newlegalvals(EXPR) = NEWVALS and
- do(add L:legalvals(EXPR) = NEWVALS)
- then set_legalvals(EXPR).
-
- /*------------ <- set_position(X_POS, Y_POS) -----------*/
-
- procedure(moving_object <- set_position(X_POS, Y_POS)) = {
- eval SELF <- setslot(x_position, X_POS);
- eval SELF <- setslot(y_position, Y_POS);
- }.
-
- /*----------- <- set_velocity(XVEL, YVEL) ---------------*/
-
- procedure(moving_object <- set_velocity(XVEL, YVEL)) = {
- eval SELF <- setslot(x_velocity, XVEL);
- eval SELF <- setslot(y_velocity, YVEL);
- }.
-
- /*------------------- simulate --------------------------*/
-
- procedure(simulate) = {
- PLANE := find_desired_plane;
- /* loop asking user what they'd like to do next */
- while next_action = ACT {
- if (not ACT == stop) {
- if (ACT == select_plane) {
- reset plane_type;
- reset plane_name;
- reset find_desired_plane;
- PLANE := find_desired_plane;
- reset next_action;
- }
- else{
- eval process(ACT, PLANE);
- reset process(ACT, PLANE);
- reset next_action;
- }
- }
- else {
- display(["Finished simulation.", nl]);
- break; /* exit the while loop */
- }
- }
- }.
-
- /*------------------- sin(ANGLE) ---------------------------*/
- /*
- This is a fact table to look-up sin for various angles, used
- in determining x and y velocities from speed. This table
- could be replaced by external functions.
- */
-
- sin(5) = 0.09.
- sin(10) = 0.17.
- sin(15) = 0.26.
- sin(20) = 0.34.
- sin(25) = 0.42.
- sin(30) = 0.5.
- sin(35) = 0.57.
- sin(40) = 0.64.
- sin(45) = 0.71.
-
- /*---------------------- speed -----------------------------*/
-
- nocache(speed).
-
- question(speed) = 'What is your flying speed (in mph)?'.
-
- legalvals(speed) = integer.
-
-
- /*------------ <- unload --------------------------------*/
-
- procedure(cargo_plane <- unload) = {
- NAME := SELF <- getslot(name);
- CARGO := SELF <- getslot(cargo);
- display(["Unloading ", NAME, ". Cargo is: ", CARGO, nl]);
- eval SELF <- setslot(cargo, []);
- }.
-
- procedure(passenger_plane <- unload) = {
- NAME := SELF <- getslot(name);
- PASS := SELF <- getslot(number_of_passengers);
- display(["Unloading ", PASS, " passengers from ", NAME, ".", nl]);
- eval SELF <- setslot(number_of_passengers, 0);
- }.
-
- /*----------------- welcome ----------------------------*/
-
- if display(['Welcome to the Flight Simulator.', nl])
- then welcome.
-
- /*----------------- X-time -----------------------------*/
- nocache(X-time).
-
- question(X-time) = ['What is the time for ', X, ', in
- hours?'].
-
- /*----------------- x_velocity --------------------------*/
-
- nocache(x_velocity).
-
- question(x_velocity) = 'What is the x velocity, in mph?'.
-
- /*------------------ y_velocity --------------------------*/
-
- nocache(y_velocity).
-
- question(y_velocity) = 'What is the y velocity, in mph? (positive
- to ascend, negative to descend)'.
-
-
-